package tau.dimes.config.db;

import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import tau.dimes.config.ConfigurationException;
import tau.dimes.config.ConfigurationNode;
import tau.dimes.config.ConfigurationSource;
import tau.dimes.util.ReflectionHelper;

public class DatabaseConfiguration
{
	private static DatabaseConfiguration instance;

	private static String SECTION_NAME = "databaseConfiguration";
	private static String DRIVERS_NODE_NAME = "drivers";
	private static String DRIVER_NODE_NAME = "driver";
	private static String SERVERS_NODE_NAME = "servers";
	private static String SERVER_NODE_NAME = "server";

	private final Map<String, Driver> drivers;
	private final Map<String, Server> servers;

	private DatabaseConfiguration(ConfigurationSource source) throws ConfigurationException
	{
		drivers = new TreeMap<String, Driver>();
		servers = new TreeMap<String, Server>();

		ConfigurationNode databaseNode = source.getConfigurationNode(SECTION_NAME);
		if (databaseNode == null)
			throw new ConfigurationException(SECTION_NAME + " is missing from configuration.");

		try
		{
			ConfigurationNode driversNode = databaseNode.getChild(DRIVERS_NODE_NAME);
			if (driversNode != null)
			{
				for (ConfigurationNode driverNode : driversNode.getChildren(DRIVER_NODE_NAME))
				{
					Driver driver = new Driver();
					ReflectionHelper.SetProperties(driver, driverNode.getAttributes());
					drivers.put(driver.getName(), driver);
				}
			}
			
			ConfigurationNode serversNode = databaseNode.getChild(SERVERS_NODE_NAME);
			if (serversNode != null)
			{
				for (ConfigurationNode serverNode : serversNode.getChildren(SERVER_NODE_NAME))
				{
					Server server = new Server();
					ReflectionHelper.SetProperties(server, serverNode.getAttributes());
					servers.put(server.getName(), server);
				}
			}
		}
		catch (Exception e)
		{
			throw new ConfigurationException(e);
		}
	}

	public static DatabaseConfiguration getInstance()
	{
		return instance;
	}

	public static void initInstance(ConfigurationSource source) throws ConfigurationException
	{
		instance = new DatabaseConfiguration(source);
	}

	public Map<String, Driver> getDrivers()
	{
		return this.drivers;
	}
	
	public Map<String, Server> getServers()
	{
		return this.servers;
	}
	
	public Set<String> getServerNames()
	{
		return this.servers.keySet();
	}
	
	public Driver getDriver(String name)
	{
		return this.drivers.get(name);
	}
	
	public Server getServer(String name)
	{
		return this.servers.get(name);
	}
}
